import os, sys, logging
import xml.dom.minidom
from optparse import make_option
from sys import stderr
from copy import copy
from django.core.management.base import BaseCommand
from django.utils.encoding import DjangoUnicodeDecodeError
#import ftbexplorer
from ftbexplorer.core.models import XMLFile, Sentence, XMLContent, TreeNode, WordTreeNode


class XMLImporter(object):
    def __init__(self, filepath):
        self.filepath = filepath
        self.fileobj = None
        self.import_file()

    def import_file(self):
        # check things
        assert os.path.exists(self.filepath), "File %s does not exists" % self.filepath
        assert os.path.isfile(self.filepath), "This is not a file : %s" % self.filepath
        # get filename
        filename = os.path.basename(self.filepath)
        # is it in the database already ?
        try:
            XMLFile.objects.get(name=filename)
            logging.warning("File %s already exits in the database, not imported twice" % filename)
            return
        except XMLFile.DoesNotExist:
            pass
        logging.info("Parsing xml")
        # parsing
        doc = xml.dom.minidom.parse(self.filepath)
        # cleaning
        clean_tree(doc)
        obj = XMLFile(name=filename)
        obj.save()
        content = doc.toxml()
        content_obj = XMLContent(content=content, file=obj)
        content_obj.save()
        # import sentences
        logging.info("Analyse des phrases")
        for child in doc.childNodes[0].childNodes:
            if child.nodeName == "SENT":
                SentenceImporter(child, obj)

        
class SentenceImporter(object):
    def __init__(self, SENT_node, file_obj):
        logging.debug("Importing sentence : %s" % (SENT_node.toxml()[:20]+u"..."))
        self.root_node = SENT_node
        self.file = file_obj
        logging.debug("Rebuilding tree in database")
        self.tree = self.import_tree(self.root_node)
        self.object = self.import_sentence()

        
    def import_tree(self, root, parent=None, sindex=0):
        name = root.nodeName
        try:
            funct = root.getAttribute('fct')
        except AttributeError:
            funct = ""
        data = ""
        if hasattr(root, 'data'):
            data = root.data.strip()
        tree_node_params = {
            "nodeName": name,
            "function": funct,
            "parent": parent, 
            "data": data,
            "sibling_index": sindex,        
        }
        if root.nodeName == 'w':
            # get attrs
            lemma = root.getAttribute('lemma')
            cat = root.getAttribute('cat')
            ee = root.getAttribute('ee')
            ei = root.getAttribute('ei')
            mph = root.getAttribute('mph')
            subcat = root.getAttribute('subcat')
            # get form
            form = get_text(root)
            # put all in the db
            node = WordTreeNode(
                # WordTreeNode params
                form = form, 
                ee=ee, ei=ei, 
                lemma=lemma, 
                mph=mph, cat=cat, 
                subcat=subcat,
                # TreeNode params
                **tree_node_params)
        else:
            node = TreeNode(**tree_node_params)
        node.save()
        if root.attributes:
            for anattr in root.attributes.values():
                node.setattr(anattr.name, anattr.value)
        child_sindex = 0
        for c in root.childNodes:
            self.import_tree(c, node, child_sindex)
            child_sindex += 1
        return node
            
    def import_sentence(self):
        assert self.root_node.nodeName == "SENT"
        # get nb
        nb = self.root_node.getAttribute('nb')
        # put xml in the database
        xml = self.root_node.toprettyxml()
        logging.debug("Adding sentence %s in database" % nb)
        sobj = Sentence(
            nb=nb, 
            xml=xml, 
            tree = self.tree,
            file=self.file)
        sobj.save()
        return sobj
    
    # def import_words(self, n):
    #     for c in n.childNodes:
    #         if c.nodeName == "w":
    #             self.windex += 1
    #             self.import_word(c)
    #         else:
    #             self.import_words(c)

    # def import_word(self, w_node):
    #     assert w_node.nodeName == "w"
    #     # get attrs
    #     lemma = w_node.getAttribute('lemma')
    #     cat = w_node.getAttribute('cat')
    #     ee = w_node.getAttribute('ee')
    #     ei = w_node.getAttribute('ei')
    #     mph = w_node.getAttribute('mph')
    #     subcat = w_node.getAttribute('subcat')
    #     # get form
    #     form = get_text(w_node)
    #     # put all in the db
    #     wobj = Word(
    #         form = form, 
    #         ee=ee, ei=ei, 
    #         lemma=lemma, 
    #         mph=mph, cat=cat, 
    #         subcat=subcat, 
    #         sentence=self.object, 
    #         index = self.windex)
    #     wobj.save()
    # 
def clean_tree(node):
    child =  copy(node.childNodes)
    for n in child:
        if n.hasChildNodes():
            clean_tree(n)
        else:
            if hasattr(n, 'data'):
                if not n.data.strip():
                    node.removeChild(n)

def get_text(node):
    if isinstance(node, xml.dom.minidom.Text):
        return node.data.strip()
    else:
        l = map(get_text, node.childNodes)
        return u" ".join(l).strip()


class Command(BaseCommand):
    help = "Import ftb files in the database"
    
    option_list = BaseCommand.option_list + (
        make_option('--debug', action='store_true', dest='debug', default=False,
            help='Display debug informations'),
    )
    args = '[--debug] files'
    
    def handle(self, *args, **options): 
        LOGGING_FORMAT="%(asctime)s - %(levelname)s - %(message)s"
        if options.get("debug", False):
            logging.basicConfig(format=LOGGING_FORMAT, level=logging.DEBUG)
        else:
            logging.basicConfig(format=LOGGING_FORMAT, level=logging.INFO)
            
            
        # loop through args to process files
        for an_arg in args:
            an_arg = os.path.abspath(an_arg)
            logging.info("Import de %s" % an_arg)
            try:
                XMLImporter(an_arg)
            except AssertionError, e:
                logging.error(str(e))


